package logic

import (
	da "admin/dao/auth"
	"admin/dto"
	m "admin/models/auth"
	"admin/utils/pagination"
	"errors"
	"fmt"
	"github.com/gin-gonic/gin"
	"gitlab.jkluck.vip/casino/golang/ca-common-util/library/log"
	"go.uber.org/zap"
)

// RolesLogic 角色业务逻辑
type RolesLogic struct {
	roleRepoInterface       da.RoleRepoInterface
	rolePermissionInterface da.RolePermissionRepoInterface
	roleMenuInterface       da.RoleMenuRepoInterface
	permissionRepoInterface da.PermissionRepoInterface
	menuRepoInterface       da.MenuRepoInterface
}

// NewRolesLogic 创建新的角色逻辑实例
// repo: 角色仓库实例
// 返回值: 角色逻辑实例指针
func NewRolesLogic(roleRepoInterface da.RoleRepoInterface, roleMenuInterface da.RoleMenuRepoInterface, rolePermissionInterface da.RolePermissionRepoInterface, permissionRepoInterface da.PermissionRepoInterface, menuRepoInterface da.MenuRepoInterface) *RolesLogic {
	// 使用GORM实现的角色仓库初始化逻辑实例
	return &RolesLogic{
		roleRepoInterface:       roleRepoInterface,
		rolePermissionInterface: rolePermissionInterface,
		roleMenuInterface:       roleMenuInterface,
		permissionRepoInterface: permissionRepoInterface,
		menuRepoInterface:       menuRepoInterface,
	}
}

// List 获取角色列表
// 返回值: 角色列表和错误信息
func (l *RolesLogic) List(ctx *gin.Context, req dto.RoleListDto) (*pagination.PageResult[m.Role], error) {
	return l.roleRepoInterface.List(ctx, req)
}

// Create 创建角色
// name: 角色名称
// 返回值: 错误信息
func (l *RolesLogic) Create(ctx *gin.Context, req dto.RoleDto) error {
	// 检查角色名称是否为空
	if req.Name == "" {
		return errors.New("角色名称不能为空")
	}
	// 检查角色名称是否重复
	if roleInfo, _ := l.roleRepoInterface.GetRoleByName(ctx, req.Name); roleInfo != nil {
		log.InfoCtx(ctx, "角色名称已存在")
		return errors.New("角色名称已存在")
	}
	createRoleInfo := &m.Role{
		Name:        req.Name,
		Description: req.Description,
	}

	// 处理权限信息
	if len(req.PermissionsID) > 0 {
		// 验证权限ID是否存在
		if err := l.validatePermissions(ctx, req.PermissionsID); err != nil {
			return err
		}
		// 关联权限
		createRoleInfo.Permissions = make([]*m.Permission, len(req.PermissionsID))
		for i, permID := range req.PermissionsID {
			createRoleInfo.Permissions[i] = &m.Permission{ID: permID}
		}
	}

	// 处理角色菜单信息
	if len(req.MenusID) > 0 {
		// 验证菜单ID是否存在
		if err := l.validateMenus(ctx, req.MenusID); err != nil {
			return err
		}
		// 关联菜单
		createRoleInfo.Menus = make([]*m.Menu, len(req.MenusID))
		for i, menuID := range req.MenusID {
			createRoleInfo.Menus[i] = &m.Menu{ID: menuID}
		}
	}

	// 调用仓库层创建角色
	return l.roleRepoInterface.Create(ctx, createRoleInfo)
}

// 验证权限是否存在
func (l *RolesLogic) validatePermissions(ctx *gin.Context, permissionIDs []int64) error {
	for _, id := range permissionIDs {
		if _, err := l.permissionRepoInterface.GetPermissionByID(id); err != nil {
			log.InfoCtx(ctx, "权限ID %d 不存在", zap.Any("permissionID", id))
			return fmt.Errorf("权限ID %d 不存在", id)
		}
	}
	return nil
}

// 验证菜单是否存在
func (l *RolesLogic) validateMenus(ctx *gin.Context, menuIDs []int64) error {
	for _, id := range menuIDs {
		if _, err := l.menuRepoInterface.GetMenuByID(id); err != nil {
			log.InfoCtx(ctx, "菜单ID %d 不存在", zap.Any("menuID", id))
			return fmt.Errorf("菜单ID %d 不存在", id)
		}
	}
	return nil
}

// Update 更新角色
// id: 角色ID
// name: 新角色名称
// 返回值: 错误信息
func (l *RolesLogic) Update(ctx *gin.Context, id int64, req dto.RoleDto) error {
	// 检查角色ID是否有效
	if id == 0 {
		return errors.New("角色ID不能为空")
	}
	// 检查角色名称是否为空
	if req.Name == "" {
		return errors.New("角色名称不能为空")
	}
	// 检查角色名称是否重复
	if roleInfo, _ := l.roleRepoInterface.GetRoleByName(ctx, req.Name); roleInfo != nil {
		log.InfoCtx(ctx, "角色名称已存在")
		return errors.New("角色名称已存在")
	}
	updateRoleInfo := &m.Role{
		Name:        req.Name,
		Description: req.Description,
	}
	if len(req.PermissionsID) > 0 {
		// 验证权限ID是否存在
		if err := l.validatePermissions(ctx, req.PermissionsID); err != nil {
			return err
		}
		// 关联权限
		updateRoleInfo.Permissions = make([]*m.Permission, len(req.PermissionsID))
		for i, permID := range req.PermissionsID {
			updateRoleInfo.Permissions[i] = &m.Permission{ID: permID}
		}
	}

	// 处理角色菜单信息
	if len(req.MenusID) > 0 {
		// 验证菜单ID是否存在
		if err := l.validateMenus(ctx, req.MenusID); err != nil {
			return err
		}
		// 关联菜单
		updateRoleInfo.Menus = make([]*m.Menu, len(req.MenusID))
		for i, menuID := range req.MenusID {
			updateRoleInfo.Menus[i] = &m.Menu{ID: menuID}
		}
	}

	// 调用仓库层创建角色
	return l.roleRepoInterface.Update(ctx, updateRoleInfo)
}

// Delete 删除角色
// id: 角色ID
// 返回值: 错误信息
func (l *RolesLogic) Delete(c *gin.Context, id int64) error {
	// 检查角色ID是否有效
	if id == 0 {
		return errors.New("角色ID不能为空")
	}
	// 调用仓库层删除角色
	return l.roleRepoInterface.Delete(c, id)
}

// GetPermissionsByRoleId 通过角色 id 获取权限
func (l *RolesLogic) GetPermissionsByRoleId(c *gin.Context, roleId int64) ([]m.Permission, error) {
	return l.rolePermissionInterface.GetPermissionsByRoleId(roleId)
}

// AddPermissionToRole 给角色添加权限
func (l *RolesLogic) AddPermissionToRole(c *gin.Context, roleId int64, req dto.AssignPermissionToRoleDto) error {
	// 检查角色ID
	if roleId == 0 {
		return errors.New("角色ID不能为空")
	}
	return l.rolePermissionInterface.AddPermissionToRole(c, roleId, req.PermissionsID)
}

// RemovePermissionFromRole 删除角色的某个权限\
func (l *RolesLogic) RemovePermissionFromRole(c *gin.Context, roleId int64, req dto.AssignPermissionToRoleDto) error {
	// 检查角色ID
	if roleId == 0 {
		return errors.New("角色ID不能为空")
	}
	return l.rolePermissionInterface.RemovePermissionFromRole(c, roleId, req.PermissionsID)
}

// GetMenusByRole 获取角色的所有菜单
func (l *RolesLogic) GetMenusByRole(roleId int64) ([]m.Menu, error) {
	return l.roleMenuInterface.GetMenusByRole(roleId)
}

// AddMenusToRole 给菜单添加权限
func (l *RolesLogic) AddMenusToRole(c *gin.Context, roleId int64, req dto.AssignMenuToRoleDto) error {
	// 检查角色ID
	if roleId == 0 {
		return errors.New("角色ID不能为空")
	}
	return l.roleMenuInterface.AddMenusToRole(c, roleId, req.MenusID)
}

// RemoveMenusFromRole 删除角色的菜单\
func (l *RolesLogic) RemoveMenusFromRole(c *gin.Context, roleId int64, req dto.AssignMenuToRoleDto) error {
	// 检查角色ID
	if roleId == 0 {
		return errors.New("角色ID不能为空")
	}
	return l.roleMenuInterface.RemoveMenusFromRole(c, roleId, req.MenusID)
}
